#include "precomp.h"

#include "MessageSystem.h"
#include "../Entity/entity.h"
#include "../World.h"

namespace Tmpl {

static MsgData* gMessages;
static int gMessagesMax;
static int gMessagesCount;

void MessageSystem::Init()
{
	gMessagesMax = 1024;
	gMessages = MALLOC64(gMessagesMax, MsgData);
	gMessagesCount = 0;
}

void MessageSystem::Clear()
{
	FREE64(gMessages);
}

void MessageSystem::HandleAllMessages()
{
	// First we execute all entity messages
	World::HandleEntityMessages();

	// Now execute the global ones
	for (int i=0; i<gMessagesCount; ++i)
	{
		ProcessMessage(gMessages[i]);
	}
	gMessagesCount = 0;
}

inline MsgData* CreateNewMessage(int creator)
{
	// store inside the entity
	if (creator != MSG_ID_IRRELEVANT)
	{
		Entity* ent = World::GetEntity(creator);
		return ent->AddNewMessage();
	}

	// store globally
	if (gMessagesCount == gMessagesMax)
	{
		gMessagesMax *= 2;
		gMessages = REALLOC64(gMessages, gMessagesMax, MsgData);
	}
	return &gMessages[gMessagesCount++];

}

void MessageSystem::AddMsgSpawnProjectile(int empireId, int ownerId, Vec2f pos, Vec2f facing, UnitData& data, int creator)
{
	MsgData* msg = CreateNewMessage(creator);
	if (msg)
	{
		msg->msgType = MsgData::MSG_SPAWN_PROJECTILE;
		msg->spawnProjectile.empireId = empireId;
		msg->spawnProjectile.ownerId = ownerId;
		msg->spawnProjectile.pos = pos;
		msg->spawnProjectile.facing = facing;
		msg->spawnProjectile.data = data;
	}
}


void MessageSystem::AddMsgDamageDone(int sender, int receiver, float damage, int creator)
{
	MsgData* msg = CreateNewMessage(creator);
	if (msg)
	{
		msg->msgType = MsgData::MSG_DAMAGE_DONE;
		msg->damageDone.sender = sender;
		msg->damageDone.receiver = receiver;
		msg->damageDone.dmg = damage;
	}
}

void MessageSystem::AddMsg(char msgType, int sender, int receiver, void* data, int creator)
{
	MsgData* msg = CreateNewMessage(creator);
	if (msg)
	{
		msg->msgType = MsgData::MSG_DEFAULT;
		msg->msgDefault.type = msgType;
		msg->msgDefault.sender = sender;
		msg->msgDefault.receiver = receiver;
		msg->msgDefault.data = data;
	}
}

void MessageSystem::ProcessMessage(const MsgData& msg)
{
	// execute the message
	switch (msg.msgType)
	{
	case MsgData::MSG_DEFAULT:
		if (msg.msgDefault.receiver != MSG_ID_IRRELEVANT)
		{
			Entity* ent = World::GetEntity(msg.msgDefault.receiver);
			if (ent && ent->IsAlive()) ent->HandleMessage(msg);
		}
		break;

	case MsgData::MSG_DAMAGE_DONE:
		if (msg.damageDone.receiver != MSG_ID_IRRELEVANT)
		{
			Entity* ent = World::GetEntity(msg.damageDone.receiver);
			if (ent && ent->IsAlive()) ent->HandleMessage(msg);
		}
		break;
	};


	// pass it to other handlers

}

}; // namespace Tmpl

